
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using Abp.Linq.Extensions;
using System.Collections.Generic;
using System.Threading.Tasks;
using Abp.Domain.Repositories;
using Precise.Products.Exporting;
using Precise.Products.Dtos;
using Precise.Dto;
using Abp.Application.Services.Dto;
using Precise.Authorization;
using Abp.Extensions;
using Abp.Authorization;
using Microsoft.EntityFrameworkCore;

namespace Precise.Products
{
	[AbpAuthorize(AppPermissions.Pages_Product)]
    public class ProductAppService : PreciseAppServiceBase, IProductAppService
    {
		 private readonly IRepository<Product, long> _productRepository;
		 private readonly IProductExcelExporter _productExcelExporter;
		 

		  public ProductAppService(IRepository<Product, long> productRepository, IProductExcelExporter productExcelExporter ) 
		  {
			_productRepository = productRepository;
			_productExcelExporter = productExcelExporter;
			
		  }

		 public async Task<PagedResultDto<GetProductForView>> GetAll(GetAllProductInput input)
         {
			
			var filteredProduct = _productRepository.GetAll()
						.WhereIf(!string.IsNullOrWhiteSpace(input.Filter), e => false  || e.Name.Contains(input.Filter) || e.Number.Contains(input.Filter) || e.Descritpion.Contains(input.Filter))
						.WhereIf(!string.IsNullOrWhiteSpace(input.Name),  e => e.Name.ToLower() == input.Name.ToLower().Trim())
						.WhereIf(!string.IsNullOrWhiteSpace(input.Number),  e => e.Number.ToLower() == input.Number.ToLower().Trim())
						.WhereIf(!string.IsNullOrWhiteSpace(input.Descritpion),  e => e.Descritpion.ToLower() == input.Descritpion.ToLower().Trim());


			var query = (from o in filteredProduct
                         select new GetProductForView() {
							Product = ObjectMapper.Map<ProductDto>(o)
						});

            var totalCount = await query.CountAsync();

            var product = await query
                .OrderBy(input.Sorting ?? "product.id asc")
                .PageBy(input)
                .ToListAsync();

            return new PagedResultDto<GetProductForView>(
                totalCount,
                product
            );
         }
		 
		 [AbpAuthorize(AppPermissions.Pages_Product_Edit)]
		 public async Task<GetProductForEditOutput> GetProductForEdit(EntityDto<long> input)
         {
            var product = await _productRepository.FirstOrDefaultAsync(input.Id);
           
		    var output = new GetProductForEditOutput {Product = ObjectMapper.Map<CreateOrEditProductDto>(product)};
			
            return output;
         }

		 public async Task CreateOrEdit(CreateOrEditProductDto input)
         {
            if(input.Id == null){
				await Create(input);
			}
			else{
				await Update(input);
			}
         }

		 [AbpAuthorize(AppPermissions.Pages_Product_Create)]
		 private async Task Create(CreateOrEditProductDto input)
         {
            var product = ObjectMapper.Map<Product>(input);

			
			if (AbpSession.TenantId != null)
			{
				product.TenantId = (int) AbpSession.TenantId;
			}
		

            await _productRepository.InsertAsync(product);
         }

		 [AbpAuthorize(AppPermissions.Pages_Product_Edit)]
		 private async Task Update(CreateOrEditProductDto input)
         {
            var product = await _productRepository.FirstOrDefaultAsync((long)input.Id);
             ObjectMapper.Map(input, product);
         }

		 [AbpAuthorize(AppPermissions.Pages_Product_Delete)]
         public async Task Delete(EntityDto<long> input)
         {
            await _productRepository.DeleteAsync(input.Id);
         } 

		public async Task<FileDto> GetProductToExcel(GetAllProductForExcelInput input)
         {
			
			var filteredProduct = _productRepository.GetAll()
						.WhereIf(!string.IsNullOrWhiteSpace(input.Filter), e => false  || e.Name.Contains(input.Filter) || e.Number.Contains(input.Filter) || e.Descritpion.Contains(input.Filter))
						.WhereIf(!string.IsNullOrWhiteSpace(input.Name),  e => e.Name.ToLower() == input.Name.ToLower().Trim())
						.WhereIf(!string.IsNullOrWhiteSpace(input.Number),  e => e.Number.ToLower() == input.Number.ToLower().Trim())
						.WhereIf(!string.IsNullOrWhiteSpace(input.Descritpion),  e => e.Descritpion.ToLower() == input.Descritpion.ToLower().Trim());


			var query = (from o in filteredProduct
                         select new GetProductForView() { 
							Product = ObjectMapper.Map<ProductDto>(o)
						 });


            var productListDtos = await query.ToListAsync();

            return _productExcelExporter.ExportToFile(productListDtos);
         }


    }
}